package org.puremvc.as3.fi.core 
{
	import org.puremvc.as3.fi.interfaces.IInjectableFacade;
	import org.puremvc.as3.fi.interfaces.IFacadeInjected;
	import org.puremvc.as3.multicore.interfaces.ICommand;
	import org.puremvc.as3.multicore.interfaces.IController;
	import org.puremvc.as3.multicore.interfaces.INotification;
	import org.puremvc.as3.multicore.patterns.observer.Observer;

	import flash.utils.Dictionary;

	/**
	 * @author a.fell
	 */
	public class Controller implements IController, IFacadeInjected 
	{
		protected var commandMap : Dictionary;
		
		protected var facade : IInjectableFacade;
		protected var multitonKey : String;

		public function Controller( key : String ) 
		{
			commandMap = new Dictionary( );
			multitonKey = key;
			initializeController();	
		}
		
		protected function initializeController() : void
		{
		}

		public function setFacade(facade : IInjectableFacade) : void
		{
			this.facade = facade;
		}

		public function registerCommand(notificationName : String, commandClassRef : Class) : void
		{
			if ( commandMap[ notificationName ] == null ) 
			{
				facade.registerObserver( notificationName, new Observer( executeCommand, this ) );
			}
			commandMap[ notificationName ] = commandClassRef;
		}
		
		public function executeCommand(notification : INotification) : void
		{
			var commandClassRef : Class = commandMap[ notification.getName() ];
			if ( commandClassRef == null ) return;

			var commandInstance : ICommand = new commandClassRef();
			
			//our implementation
			with( commandInstance as IFacadeInjected )
			{
				setFacade(facade);
			}
			
			commandInstance.initializeNotifier( multitonKey );
			commandInstance.execute( notification );
		}
		
		public function removeCommand(notificationName : String) : void
		{
			// if the Command is registered...
			if ( hasCommand( notificationName ) )
			{
				// remove the observer
				facade.removeObserver( notificationName, this );
							
				// remove the command
				commandMap[ notificationName ] = null;
			}
		}
		
		public function hasCommand(notificationName : String) : Boolean
		{
			return commandMap[ notificationName ] != null;
		}
		
		public function hasFacade() : Boolean
		{
			return facade != null;
		}
	}
}
